/*
 * Copyright 2008 echo.khannedy@gmail.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ["Let's ROCK with JAVA"]
 * 
 * ["echo.khannedy@gmail.com"]
 * ["http://eecchhoo.wordpress.com/"]
 */
package open.usu.swing;

import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import open.usu.swing.handler.ImageHandlers;

/**
 * Komponen ini merupakan komponen yang bekerja ketika terjadi proses drag. 
 * EDragAndDrop akan menampilkan data ketika user melakukan proses drag. Misal
 * user melakukan drag teks (String), maka EDragAndDrop akan menampilkan tulisan, 
 * jika user mendrag file, maka EDragAndDrop akan menampilkan gambar file, jika 
 * user mendrag gambar maka EDragAndDrop akan menampilkan gambar
 * 
 * @author usu
 * @author <a href="mailto:echo.khannedy@gmail.com">echo.khannedy@gmail.com</a>
 * @see <a href="http://eecchhoo.wordpress.com/">http://eecchhoo.wordpress.com/</a>
 * @see <a href="http://biosmansa.wordpress.com/">http://biosmansa.wordpress.com/</a>
 * @see <a href="http://code.google.com/p/eglasspane/">http://code.google.com/p/eglasspane/</a>
 */
public class EDragAndDrop extends JComponent {
    // <editor-fold defaultstate="collapsed" desc="Field Code">
    private static final long serialVersionUID = -8694033259196806542L;
    private static final int TYPE_NONE = 0;
    private static final int TYPE_STRING = 1;
    private static final int TYPE_IMAGE = 2;
    private static final int TYPE_FILES = 3;
    private static final int TYPE_UNKNOWN = 4;
    /**
     * Properti untuk theme
     */
    public static final String PROPERTY_THEME = "PROPERTY_THEME";
    /**
     * Properti untuk alpha
     */
    public static final String PROPERTY_ALPHA = "PROPERTY_ALPHA";
    private int type = TYPE_NONE;
    private Image currentImage;
    private Point currentLocation;
    private List<File> tempFiles;
    private StringBuilder tempString = new StringBuilder();
    private AlphaComposite alphaComposite = AlphaComposite.SrcOver;
    private File tempFile;
    private Theme theme;
    private int alpha;
// </editor-fold>
    /**
     * Membuat EDragAndDrop baru
     */
    public EDragAndDrop() {
        super();

        // mengubah opaque menjadi false
        super.setOpaque(false);

        // mengubah theme menjadi default
        setTheme(Theme.DEFAULT);

        // mengubah alpha default menjadi 50
        setAlpha(50);
    }

    /**
     * mendapatkan nilai alpha
     * @return nilai alpha
     */
    public int getAlpha() {
        return alpha;
    }

    /**
     * mengubah nilai alpha, jika nilai baru lebih dari 100, maka akan dirubah 
     * menjadi 100, dan jika nilai baru kurang dari 0 maka akan dirubah menjadi 0
     * @param alpha nilai baru
     */
    public void setAlpha(int alpha) {
        if (alpha > 100) {
            alpha = 100;
        } else if (alpha < 0) {
            alpha = 0;
        }

        // mendapatkan nilai lama
        int oldValue = getAlpha();

        // mengubah nilai lama
        this.alpha = alpha;

        // memberi tahu bahwa alpha telah berubah
        firePropertyChange(PROPERTY_ALPHA, oldValue, alpha);

        // mengubah alpha komposite
        alphaComposite = alphaComposite.derive(getAlpha() / 100F);
        repaint();
    }

    /**
     * mendapatkan tema yang sedang digunakan
     * @return Theme
     */
    public Theme getTheme() {
        return theme;
    }

    /**
     * menggubah tema yang sedang dipakai
     * @param theme tema baru
     */
    public void setTheme(Theme theme) {
        // mendapatkan nilai lama
        Theme oldValue = getTheme();

        // mengubah tema lama
        this.theme = theme;

        // memberi tahu bahwa tema berubah
        firePropertyChange(PROPERTY_THEME, oldValue, theme);
    }

    /**
     * bersiap untuk melakukan drag
     * @param transferable
     * @throws java.awt.datatransfer.UnsupportedFlavorException
     * @throws java.io.IOException
     */
    @SuppressWarnings("unchecked")
    public void drag(Transferable transferable) throws UnsupportedFlavorException, IOException {
        if (transferable.isDataFlavorSupported(DataFlavor.imageFlavor)) {
            setType(TYPE_IMAGE);
            currentImage = (Image) transferable.getTransferData(DataFlavor.imageFlavor);
            setCurrentImage(currentImage.getScaledInstance(128, -1, Image.SCALE_FAST));
        } else if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            setType(TYPE_FILES);
            tempFiles = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
            if (tempFiles.size() > 1) {
                if (getTheme() == Theme.IRON) {
                    setCurrentImage(ImageHandlers.IronTheme.ImageBlank);
                } else {
                    setCurrentImage(ImageHandlers.ImageBlank);
                }
            } else {
                tempFile = tempFiles.get(0);
                if (tempFile.isDirectory()) {
                    if (getTheme() == Theme.IRON) {
                        setCurrentImage(ImageHandlers.IronTheme.ImageFolder);
                    } else {
                        setCurrentImage(ImageHandlers.ImageFolder);
                    }
                } else {
                    if (tempString.length() > 0) {
                        tempString.delete(0, tempString.length() - 1);
                    }
                    tempString.append(tempFile.getName().toUpperCase());
                    if (tempString.toString().endsWith(".BMP") || tempString.toString().endsWith(".JPG") ||
                            tempString.toString().endsWith(".PNG") || tempString.toString().endsWith(".GIF")) {
                        currentImage = ImageIO.read(tempFile);
                        setCurrentImage(currentImage.getScaledInstance(128, -1, Image.SCALE_FAST));
                    } else if (tempString.toString().endsWith(".ZIP") || tempString.toString().endsWith(".RAR") ||
                            tempString.toString().endsWith(".BIN") || tempString.toString().endsWith(".7Z") ||
                            tempString.toString().endsWith(".JAR") || tempString.toString().endsWith(".WAR") ||
                            tempString.toString().endsWith(".EAR")) {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageArchive);
                        } else {
                            setCurrentImage(ImageHandlers.ImageArchive);
                        }
                    } else if (tempString.toString().endsWith(".DOC") || tempString.toString().endsWith(".RTF") ||
                            tempString.toString().endsWith(".PPT") || tempString.toString().endsWith(".XLS")) {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageDocument);
                        } else {
                            setCurrentImage(ImageHandlers.ImageDocument);
                        }
                    } else if (tempString.toString().endsWith(".HTM") || tempString.toString().endsWith(".HTML") ||
                            tempString.toString().endsWith(".JS") || tempString.toString().endsWith(".CSS") ||
                            tempString.toString().endsWith(".PHP") || tempString.toString().endsWith(".ASP") ||
                            tempString.toString().endsWith(".JSP") || tempString.toString().endsWith(".XML")) {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageWeb);
                        } else {
                            setCurrentImage(ImageHandlers.ImageWeb);
                        }
                    } else if (tempString.toString().endsWith(".EXE") || tempString.toString().endsWith(".BAT") ||
                            tempString.toString().endsWith(".COM")) {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageApplication);
                        } else {
                            setCurrentImage(ImageHandlers.ImageApplication);
                        }
                    } else if (tempString.toString().endsWith(".MP3") || tempString.toString().endsWith(".WAV") ||
                            tempString.toString().endsWith(".AAC") || tempString.toString().endsWith(".WMA") ||
                            tempString.toString().endsWith(".M4A") || tempString.toString().endsWith(".AMR")) {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageMusic);
                        } else {
                            setCurrentImage(ImageHandlers.ImageMusic);
                        }
                    } else if (tempString.toString().endsWith(".MP4") || tempString.toString().endsWith(".MPG") ||
                            tempString.toString().endsWith(".AVI") || tempString.toString().endsWith(".WMV") ||
                            tempString.toString().endsWith(".3GP") || tempString.toString().endsWith(".MOV") ||
                            tempString.toString().endsWith(".RM") || tempString.toString().endsWith(".FLV") ||
                            tempString.toString().endsWith(".ASF") || tempString.toString().endsWith(".MPEG")) {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageMovie);
                        } else {
                            setCurrentImage(ImageHandlers.ImageMovie);
                        }
                    } else {
                        if (getTheme() == Theme.IRON) {
                            setCurrentImage(ImageHandlers.IronTheme.ImageBlank);
                        } else {
                            setCurrentImage(ImageHandlers.ImageBlank);
                        }
                    }
                }
            }
        } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            setType(TYPE_STRING);
            setCurrentImage(ImageHandlers.ImageBlank);
        } else {
            setType(TYPE_UNKNOWN);
            setCurrentImage(ImageHandlers.ImageBlank);
        }
    }

    /**
     * Memanggil aksi start drag
     * @param location lokasi mouse
     */
    public void startDrag(Point location) {
        setCurrentLocation(location);
    }

    /**
     * Memanggil aksi start drag, dengan lokasi mouse menurut EDragAndDrop
     */
    public void startDrag() {
        startDrag(getMousePosition());
    }

    /**
     * Memanggil aksi drop
     */
    public void drop() {
        setType(TYPE_NONE);
        repaint();
    }

    private void setCurrentLocation(Point currentLocation) {
        this.currentLocation = currentLocation;
        repaint();
    }

    private void setType(int type) {
        this.type = type;
    }

    private void setCurrentImage(Image currentImage) {
        this.currentImage = currentImage;
    }

    @Override
    @Deprecated
    public void setOpaque(boolean isOpaque) {
        super.setOpaque(false);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // apakah siap untuk melakukan penggambaran drag
        if (currentImage != null && currentLocation != null && type != TYPE_NONE) {
            // menggambar graphics
            paintDrag(g);
        }
    }

    /**
     * mengambar efek drag
     * @param g
     */
    protected void paintDrag(Graphics g) {
        // menkonversikan graphics
        Graphics2D g2 = (Graphics2D) g.create();

        // menggambar drag
        g2.setComposite(alphaComposite);
        g2.drawImage(currentImage, currentLocation.x, currentLocation.y, this);

        // menghilangkan graphics
        g2.dispose();
    }
}
